#include "LogicFlag.h"

string LogicFlag::flagTaskByIndex(Parser::PARSED_COMMAND parsedCommand, 
									vector<Task>& tasksVector,
									Data* _data,
									Writer* _writer) {

	string statusMessage;
	string taskName;
	int taskID;
	int index;
	Data::DataFeedback dataFeedback;
	vector<Task> tasks;
	bool flagState;
	bool outOfBounds;

	index = parsedCommand.editTaskID;

	outOfBounds = isOutOfBounds(index, tasksVector.size());

	if( outOfBounds ) {
		throw(INDEX_OUT_OF_BOUNDS_ERROR_MESSAGE);
	}

	taskID = tasksVector[index-1].getTaskID();

	_data->getByID(tasks, taskID);

	if( tasks.empty() ) {
		throw(NOT_FOUND_ERROR_MESSAGE);
	}

	if( tasksVector[index-1].getFlag() == false ) {
		flagState = true;
	} else {
		flagState = false;
	}

	_task = tasksVector[index-1];
	_task.setFlag(flagState);

	dataFeedback = _data->executeEdit(_task);

	if( dataFeedback == Data::FAILURE ) {
		throw(FLAG_ERROR_MESSAGE);
		//logErrors(FLAG_ERROR_MESSAGE, _undoState);
	}

	if( dataFeedback == Data::SUCCESS ) {
		tasksVector.clear();
		tasksVector.push_back(_task);
		tasks.clear();
		_data->getAll(tasks);
		_writer->write(tasks);

		if( flagState ) {
			statusMessage = FLAG_SUCCESS_MESSAGE;
		} else {
			statusMessage = UNFLAG_SUCCESS_MESSAGE;
		}
	}

	return statusMessage;
}

string LogicFlag::flagTaskByName(Parser::PARSED_COMMAND parsedCommand, 
									vector<Task>& tasksVector,
									Data* _data,
									Writer* _writer) {
	
	string statusMessage;
	string taskName;
	int taskID;
	Data::DataFeedback dataFeedback;
	vector<Task> tasks;
	bool multipleMatch;
	bool executed;
	bool flagState;

	taskName = parsedCommand.editTaskName;

	_data->getByName(tasks, taskName);

	if( tasks.empty() ) {
		throw(NOT_FOUND_ERROR_MESSAGE);
	}

	tasksVector.clear();

	multipleMatch = isMultipleMatch(tasks.size());

	if( multipleMatch ) {
		copyTasks(tasks, tasksVector);
		executed = false;
	} else {
		_task = tasks[FIRST_POSITION];
		flagState = _task.getFlag();
		_task.setFlag(!flagState);
		tasksVector.push_back(_task);
		taskID = _task.getTaskID();
		dataFeedback = _data->executeEdit(_task);
		executed = true;
	}

	if( executed == true && dataFeedback == Data::SUCCESS ) {
		tasks.clear();
		_data->getAll(tasks);
		_writer->write(tasks);
		statusMessage = FLAG_SUCCESS_MESSAGE;
	} else {
		statusMessage = FLAG_ERROR_MESSAGE;
		//logErrors(statusMessage, _undoState);
	}

	return statusMessage;
}

void LogicFlag::copyTasks(vector<Task>& tasks, vector<Task>& tasksVector) {
	for( unsigned int i=0; i<tasks.size(); i++ ) {
		tasksVector.push_back(tasks[i]);
	}
}

bool LogicFlag::isOutOfBounds(int index, int size) {
	bool outOfBounds;

	if( index <= 0 ) {
		outOfBounds = true;
	} else if( index > size ) {
		outOfBounds = true;
	} else {
		outOfBounds = false;
	}

	return outOfBounds;
}

bool LogicFlag::isMultipleMatch(int size) {
	
	bool multipleMatch;
	
	if( size == 1 ) {
		multipleMatch = false;
	} else {
		multipleMatch = true;
	}

	return multipleMatch;
}

const string LogicFlag::FLAG_SUCCESS_MESSAGE = "Item Flagged";
const string LogicFlag::UNFLAG_SUCCESS_MESSAGE = "Item Un-flagged";

const string LogicFlag::FLAG_ERROR_MESSAGE = "Unable To Flag";
const string LogicFlag::UNFLAG_ERROR_MESSAGE = "Unable to Un-flag";

const int LogicFlag::FIRST_POSITION = 0;

const string LogicFlag::NOT_FOUND_ERROR_MESSAGE = "Task Not Found";
const string LogicFlag::INDEX_OUT_OF_BOUNDS_ERROR_MESSAGE = "Invalid Task Number";